using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Castle.DynamicProxy;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;

namespace MatrixFramework.Shared.Application.Caching
{
    /// <summary>
    /// 缓存拦截器
    /// </summary>
    public class CacheInterceptor : IInterceptor, ITransientDependency
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<CacheInterceptor> _logger;

        public CacheInterceptor(IServiceProvider serviceProvider, ILogger<CacheInterceptor> logger)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
        }

        public void Intercept(IInvocation invocation)
        {
            var cacheAttribute = GetCacheAttribute(invocation.Method);
            if (cacheAttribute == null || !cacheAttribute.Enabled)
            {
                invocation.Proceed();
                return;
            }

            var cacheManager = _serviceProvider.GetRequiredService<DistributedCacheManager>();
            var keyManager = _serviceProvider.GetRequiredService<CacheKeyManager>();

            var cacheKey = GenerateCacheKey(invocation, cacheAttribute, keyManager);

            // 检查缓存
            var cachedResult = cacheManager.GetAsync<object>(cacheKey).Result;
            if (cachedResult != null)
            {
                invocation.ReturnValue = cachedResult;
                _logger.LogDebug("缓存命中: {CacheKey}", cacheKey);
                return;
            }

            // 缓存未命中，执行方法
            invocation.Proceed();

            // 缓存结果
            if (invocation.ReturnValue != null)
            {
                var expiration = TimeSpan.FromMinutes(cacheAttribute.ExpirationMinutes);
                cacheManager.SetAsync(cacheKey, invocation.ReturnValue, expiration).Wait();
                _logger.LogDebug("缓存设置: {CacheKey}", cacheKey);
            }

            // 处理缓存失效
            HandleCacheEviction(invocation, keyManager, cacheManager);
        }

        private CacheAttribute? GetCacheAttribute(MethodInfo method)
        {
            return method.GetCustomAttributes<CacheAttribute>(true)
                .FirstOrDefault();
        }

        private List<CacheEvictAttribute> GetCacheEvictAttributes(MethodInfo method)
        {
            return method.GetCustomAttributes<CacheEvictAttribute>(true).ToList();
        }

        private string GenerateCacheKey(IInvocation invocation, CacheAttribute cacheAttribute, CacheKeyManager keyManager)
        {
            var keyParts = new List<string>();

            // 添加前缀
            if (!string.IsNullOrEmpty(cacheAttribute.KeyPrefix))
            {
                keyParts.Add(cacheAttribute.KeyPrefix);
            }
            else
            {
                keyParts.Add(invocation.TargetType.Name);
                keyParts.Add(invocation.Method.Name);
            }

            // 添加用户ID
            if (cacheAttribute.PerUser)
            {
                // 这里需要从当前上下文获取用户ID
                // 简化处理，实际应用中需要注入ICurrentUser
                keyParts.Add("user:unknown");
            }

            // 添加租户ID
            if (cacheAttribute.PerTenant)
            {
                // 这里需要从当前上下文获取租户ID
                // 简化处理，实际应用中需要注入ICurrentTenant
                keyParts.Add("tenant:unknown");
            }

            // 添加参数
            if (cacheAttribute.KeyParamIndexes.Any())
            {
                foreach (var index in cacheAttribute.KeyParamIndexes)
                {
                    if (index >= 0 && index < invocation.Arguments.Length)
                    {
                        var param = invocation.Arguments[index];
                        if (param != null)
                        {
                            keyParts.Add(param.ToString() ?? "null");
                        }
                    }
                }
            }
            else
            {
                // 默认使用所有参数
                foreach (var arg in invocation.Arguments)
                {
                    if (arg != null)
                    {
                        // 对于复杂对象，使用类型名和哈希值
                        var paramValue = arg.GetType().IsValueType || arg is string
                            ? arg.ToString()
                            : $"{arg.GetType().Name}:{arg.GetHashCode():X}";
                        keyParts.Add(paramValue);
                    }
                }
            }

            return keyManager.GenerateUniqueKey(keyParts[0], keyParts.Skip(1).ToArray());
        }

        private void HandleCacheEviction(IInvocation invocation, CacheKeyManager keyManager, DistributedCacheManager cacheManager)
        {
            var evictAttributes = GetCacheEvictAttributes(invocation.Method);
            if (!evictAttributes.Any()) return;

            foreach (var evictAttr in evictAttributes)
            {
                if (evictAttr.BeforeInvocation)
                {
                    continue; // 已经在方法执行前处理过了
                }

                Task.Run(async () =>
                {
                    await HandleCacheEvictionAsync(invocation, keyManager, cacheManager, evictAttr);
                });
            }
        }

        private async Task HandleCacheEvictionAsync(IInvocation invocation, CacheKeyManager keyManager, DistributedCacheManager cacheManager, CacheEvictAttribute evictAttr)
        {
            try
            {
                if (evictAttr.AllEntries)
                {
                    // 失效所有缓存 - 这个操作比较危险，需要谨慎使用
                    _logger.LogWarning("执行全部缓存失效操作");
                    return;
                }

                var keysToEvict = new List<string>();

                if (evictAttr.CacheKeys != null && evictAttr.CacheKeys.Any())
                {
                    keysToEvict.AddRange(evictAttr.CacheKeys);
                }

                if (evictAttr.KeyPattern != null)
                {
                    // 根据模式失效缓存
                    var patternKeys = await GetCacheKeysByPattern(evictAttr.KeyPattern);
                    keysToEvict.AddRange(patternKeys);
                }

                foreach (var key in keysToEvict)
                {
                    await cacheManager.RemoveAsync(key);
                    _logger.LogDebug("缓存失效: {CacheKey}", key);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存失效操作失败");
            }
        }

        private async Task<List<string>> GetCacheKeysByPattern(string pattern)
        {
            // 这里应该实现根据模式获取缓存键的逻辑
            // 由于这是一个复杂的实现，这里返回空列表作为占位符
            await Task.CompletedTask;
            return new List<string>();
        }

        private async Task HandleCacheEvictionAsync(IInvocation invocation, CacheKeyManager keyManager, DistributedCacheManager cacheManager)
        {
            var evictAttributes = GetCacheEvictAttributes(invocation.Method);
            if (!evictAttributes.Any()) return;

            foreach (var evictAttr in evictAttributes)
            {
                await HandleCacheEvictionAsync(invocation, keyManager, cacheManager, evictAttr);
            }
        }
    }
}